package dao

import (
	"context"
	"device-admin/config/mysql"
	"device-admin/config/redis"
	"device-admin/internal/dal"
	"device-admin/internal/define"
	"device-admin/internal/models"
	"strconv"
	"strings"
	"time"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/logx"
	go_redis "github.com/go-redis/redis/v8"
	"github.com/samber/lo"

	"gorm.io/gorm"
)

type Terminal struct{}
type TerminalList struct {
	models.Terminal
	Online     int    `json:"online" gorm:"-"`                       // 在线状态
	DeviceType int    `json:"device_type" gorm:"column:device_type"` // 设备类型
	ProvinceID string `json:"-" gorm:"column:province_id"`           // 省份id
	CityID     string `json:"-" gorm:"column:city_id"`               // 城市id
	DistrictID string `json:"-" gorm:"column:district_id"`           // 区县id
	LocationID string `json:"-" gorm:"column:location_id"`           // 位置id
	MerchantID string `json:"-" gorm:"column:merchant_id"`           // 商户id
	Province   string `json:"province" gorm:"-"`                     // 省份
	City       string `json:"city" gorm:"-"`                         // 城市
	District   string `json:"district" gorm:"-"`                     // 区县
	Location   string `json:"location" gorm:"-"`                     // 位置
	Merchant   string `json:"merchant" gorm:"-"`                     // 商户名称
}

// VersionOption 终端版本选项
func (Terminal) VersionOption(ctx context.Context, query *dal.Query, terminalType string) []string {
	t := dal.Terminal
	tx := t.WithContext(ctx)
	// 设备类型
	if terminalType != "" {
		tx = tx.Where(t.TerminalType.Eq(terminalType))
	}
	var versions []string
	tx.Distinct(t.CurrentVersion).
		Pluck(t.CurrentVersion, &versions)
	return versions
}

// List 终端列表
func (Terminal) List(
	ctx context.Context,
	query *dal.Query,
	loginUserMerchantID,
	loginUserMerchantPath string,
	robotID, terminalType string,
	online int,
	version string, // 软件版本
	provinceID, cityID, districtID string, //省市区id，多个以逗号分隔
	page, limit int,
) (list []TerminalList, total int64, err error) {
	t := dal.Terminal
	d := dal.Device
	l := dal.Location
	dx := d.WithContext(ctx)
	tx := t.WithContext(ctx)
	lx := l.WithContext(ctx)
	// 设备id
	if robotID != "" {
		tx = tx.Where(t.RobotID.Like("%" + robotID + "%"))
	}
	// 设备类型
	if terminalType != "" {
		tx = tx.Where(t.TerminalType.Eq(terminalType))
	}
	// 终端的软件版本
	if version != "" {
		tx = tx.Where(t.CurrentVersion.Like("%" + version + "%"))
	}
	// group查询条件
	// 省份条件
	areaGroup := l.WithContext(ctx)
	{
		if provinceID != "" {
			areaGroup = areaGroup.Or(l.ProvinceID.In(strings.Split(provinceID, ",")...))
		}
		// 城市条件
		if cityID != "" {
			areaGroup = areaGroup.Or(l.CityID.In(strings.Split(cityID, ",")...))
		}
		// 区县条件
		if districtID != "" {
			areaGroup = areaGroup.Or(l.DistrictID.In(strings.Split(districtID, ",")...))
		}
	}
	// 加上group条件
	tx.Where(areaGroup)

	// 在线状态过滤
	if online == 0 {
		tx = tx.Where(t.LatestActiveTime.Lt(time.Now().Unix() - 60))
	} else if online == 1 {
		tx = tx.Where(t.LatestActiveTime.Gt(time.Now().Unix() - 60))
	}

	{
		// 如果不是平台用户，则只能看到自己或下级商户的设备
		if loginUserMerchantID != "1" {
			merchantPath := strings.Join([]string{loginUserMerchantPath, loginUserMerchantID}, ">")
			tx = tx.Where(d.MerchantPath.Like(merchantPath + "%"))
		}
	}

	tx = tx.LeftJoin(dx, t.RobotID.EqCol(d.RobotID)).
		LeftJoin(lx, l.ID.EqCol(d.LocationID))
	// 获取设备总数
	total, _ = tx.Count()
	tx.Select(t.ALL, d.DeviceType, d.LocationID, d.MerchantID, l.ProvinceID, l.CityID, l.DistrictID).
		Offset(GetPageOffset(page, limit)).
		Order(t.RobotID).
		Limit(GetPageLimit(limit)).
		Scan(&list)
	for index, record := range list {
		if record.LatestActiveTime < time.Now().Unix()-60 {
			list[index].Online = 0
		} else {
			list[index].Online = 1
		}
	}
	return list, total, nil
}

type StatusListType struct {
	ID                 string `json:"id" gorm:"column:id"`
	RobotID            string `json:"robot_id" gorm:"column:robot_id"`
	MerchantID         string `json:"-" gorm:"column:merchant_id"`
	Merchant           string `json:"merchant" gorm:"-"`
	Battery            int8   `json:"battery" gorm:"column:battery"`
	ProvinceID         string `json:"-" gorm:"column:province_id"`
	Province           string `json:"province" gorm:"-"`
	CityID             string `json:"-" gorm:"column:city_id"`
	City               string `json:"city" gorm:"-"`
	DistrictID         string `json:"-" gorm:"column:district_id"`
	District           string `json:"district" gorm:"-"`
	LocationID         string `json:"-" gorm:"column:location_id"`
	Location           string `json:"location" gorm:"-"`
	FloorID            string `json:"-" gorm:"column:floor_id"`
	Floor              string `json:"floor"`
	PositionID         string `json:"-" gorm:"column:position_id"`
	Position           string `json:"position"`
	Mode               string `json:"mode" gorm:"column:mode"`
	SubMode            string `json:"sub_mode" gorm:"column:sub_mode"`
	Online95           int8   `json:"online95" gorm:"column:online95"`
	Online97           int8   `json:"online97" gorm:"column:online97"`
	Online98           int8   `json:"online98" gorm:"column:online98"`
	SaleStatus         int8   `json:"sale_status" gorm:"-"`
	ToTaskDuration     int64  `json:"to_task_duration" gorm:"column:to_task_duration"`
	TaskDuration       int64  `json:"task_duration" gorm:"column:task_duration"`
	ToChargingDuration int64  `json:"to_charging_duration" gorm:"column:to_charging_duration"`
	LatestActiveTime   int64  `json:"latest_active_time" gorm:"column:latest_active_time"`
	LatestActiveTime97 int64  `json:"latest_active_time_97" gorm:"column:latest_active_time_97"`
	LatestActiveTime98 int64  `json:"latest_active_time_98" gorm:"column:latest_active_time_98"`
}

// List 终端列表
func (Terminal) StatusList(
	ctx context.Context,
	query *dal.Query,
	loginUserMerchantID,
	loginUserMerchantPath string,
	merchantPath []string, // 商户id，多个以逗号分隔
	robotID string, // 设备id，多个以逗号分隔
	online int, // 在线状态0-全部,1-95在线，2-95离线，3-97在线，4-97离线，5-98在线，6-98离线
	provinceID, cityID, districtID string, //省市区id，多个以逗号分隔
	locationID string, // 位置id，多个以逗号分隔
	workMode int, // 模式类型，多个以逗号分隔
	saleStatus int, // 售卖状态
	page, limit int, // 分页参数
) (
	list []StatusListType, // 设备列表
	total int64, // 设备总数
	err error,
) {
	t := dal.Terminal
	d := dal.Device
	l := dal.Location
	dx := d.WithContext(ctx)
	lx := l.WithContext(ctx)
	deviceStatusList := []StatusListType{}
	// 获取满足条件的设备id
	{
		// 联合终端表 + 设备表 + 位置表
		dx = dx.LeftJoin(lx, l.ID.EqCol(d.LocationID))
		// 设备id
		if robotID != "" {
			dx = dx.Where(d.RobotID.In(strings.Split(robotID, ",")...))
		}
		// group查询条件
		// 省份条件
		areaGroup := l.WithContext(ctx)
		{
			if provinceID != "" {
				areaGroup = areaGroup.Or(l.ProvinceID.In(strings.Split(provinceID, ",")...))
			}
			// 城市条件
			if cityID != "" {
				areaGroup = areaGroup.Or(l.CityID.In(strings.Split(cityID, ",")...))
			}
			// 区县条件
			if districtID != "" {
				areaGroup = areaGroup.Or(l.DistrictID.In(strings.Split(districtID, ",")...))
			}
		}
		// 加上group条件
		dx.Where(areaGroup)
		// 所属位置
		if locationID != "" {
			dx.Where(l.ID.In(strings.Split(locationID, ",")...))
		}
		// 设备模式
		if workMode > 0 {
			robotIDs, err := Terminal{}.getWorkModeRobotIDs(workMode)
			if err != nil {
				return nil, 0, err
			}
			dx.Where(d.RobotID.In(robotIDs...))
		}
		// 售卖状态
		if saleStatus > 0 { //getSaleStatusRobotIDs
			robotIDs, err := Terminal{}.GetSaleStatusRobotIDs(1)
			if err != nil {
				return nil, 0, err
			}
			if saleStatus == 1 {
				dx.Where(d.RobotID.In(robotIDs...))
			} else {
				dx.Where(d.RobotID.NotIn(robotIDs...))
			}
		}
		// 商户过滤
		{
			// 如果不是平台用户，则只能看到自己或下级商户的设备
			if loginUserMerchantID != "1" && loginUserMerchantID != "" {
				dx = dx.Where(d.MerchantPath.Like(loginUserMerchantPath + "%"))
			} else if loginUserMerchantID == "1" {
				dx = dx.Where(d.MerchantPath.Like(">1>%")) // 过滤掉管理员下的设备
			}
			if len(merchantPath) > 0 {
				dx = dx.Where(d.MerchantPath.In(merchantPath...))
			}
		}
		// 过滤掉未启用的设备
		dx = dx.Where(d.LatestActiveTime.Gt(0))
	}
	// 表别名
	t1 := t.As("t1")
	t2 := t.As("t2")
	t3 := t.As("t3")
	// 子查询
	sq1 := t.WithContext(ctx).Where(t.TerminalType.Eq("95")).Select(t.RobotID, t.LatestActiveTime).As("t1")
	sq2 := t.WithContext(ctx).Where(t.TerminalType.Eq("97")).Select(t.RobotID, t.LatestActiveTime).As("t2")
	sq3 := t.WithContext(ctx).Where(t.TerminalType.Eq("98")).Select(t.RobotID, t.LatestActiveTime).As("t3")
	// 联表
	{
		dx.LeftJoin(sq1, t1.RobotID.EqCol(d.RobotID)).
			LeftJoin(sq2, t2.RobotID.EqCol(d.RobotID)).
			LeftJoin(sq3, t3.RobotID.EqCol(d.RobotID))
	}
	// 在线条件
	{
		if online == 1 {
			dx = dx.Where(t1.LatestActiveTime.Gte(time.Now().Unix() - 60))
		} else if online == 2 {
			dx = dx.Where(t1.LatestActiveTime.Lt(time.Now().Unix() - 60))
		} else if online == 3 {
			dx = dx.Where(t2.LatestActiveTime.Gte(time.Now().Unix() - 60))
		} else if online == 4 {
			dx = dx.Where(t2.LatestActiveTime.Lt(time.Now().Unix() - 60))
		} else if online == 5 {
			dx = dx.Where(t3.LatestActiveTime.Gte(time.Now().Unix() - 60))
		} else if online == 6 {
			dx = dx.Where(t3.LatestActiveTime.Lt(time.Now().Unix() - 60))
		} else if online == 7 {
			dx = dx.Where(t1.LatestActiveTime.Lt(time.Now().Unix() - 60))
			dx = dx.Where(t2.LatestActiveTime.Lt(time.Now().Unix() - 60))
			dx = dx.Where(t3.LatestActiveTime.Lt(time.Now().Unix() - 60))
		}
	}
	// 计算总数
	tx1 := dx.Session(&gorm.Session{})
	total, _ = tx1.Select(d.RobotID).Distinct(d.RobotID).Count()

	// 查询结果
	tx1.Select(
		d.ID,
		t1.LatestActiveTime.As("latest_active_time"),
		t2.LatestActiveTime.As("latest_active_time_97"),
		t3.LatestActiveTime.As("latest_active_time_98"),
		d.RobotID,
		d.MerchantID,
		d.Battery,
		d.FloorID, d.PositionID, // 楼层id，楼层位置
		l.ProvinceID, l.CityID, l.DistrictID, // 省市区商场
		l.ID.As("location_id"),
	).
		Offset(GetPageOffset(page, limit)).
		Limit(GetPageLimit(limit)).
		Order(d.RobotID.Asc()).
		Scan(&deviceStatusList)
	for index, deviceStatus := range deviceStatusList {
		if deviceStatus.LatestActiveTime > time.Now().Unix()-60 {
			deviceStatusList[index].Online95 = 1
		}
		if deviceStatus.LatestActiveTime97 > time.Now().Unix()-60 {
			deviceStatusList[index].Online97 = 1
		}
		if deviceStatus.LatestActiveTime98 > time.Now().Unix()-60 {
			deviceStatusList[index].Online98 = 1
		}
	}

	return deviceStatusList, total, nil
}

// GetSubModeRobotIDs 获取某个子模式的设备
func (Terminal) GetSubModeRobotIDs(subMode int) ([]string, error) {
	robotIDs := []string{}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
	defer cancel()
	rdb := redis.NewDB()
	keys, _ := rdb.Keys(ctx, "*"+define.RedisRobotRTInfo+"*").Result()

	cmds, _ := redis.NewDB().Pipelined(ctx, func(pipe go_redis.Pipeliner) error {
		for _, key := range keys {
			pipe.HGet(ctx, key, "sub_mode") // 工作模式
		}
		return nil
	})
	if len(keys) != len(cmds) {
		return nil, errorx.New("工作模式设备获取失败", -1)
	}
	for index, cmd := range cmds {
		valInt, _ := strconv.Atoi(cmd.(*go_redis.StringCmd).Val())
		if valInt == subMode {
			arr := strings.Split(keys[index], ":")
			robotIDs = append(robotIDs, arr[len(arr)-1])
		}
	}
	return robotIDs, nil
}

// getWorkModeRobotIDs 获取某个工作模式的设备
func (Terminal) getWorkModeRobotIDs(workMode int) ([]string, error) {
	robotIDs := []string{}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
	defer cancel()
	rdb := redis.NewDB()
	keys, _ := rdb.Keys(ctx, "*"+define.RedisRobotRTInfo+"*").Result()

	cmds, _ := redis.NewDB().Pipelined(ctx, func(pipe go_redis.Pipeliner) error {
		for _, key := range keys {
			pipe.HGet(ctx, key, "work_mode") // 工作模式
		}
		return nil
	})
	if len(keys) != len(cmds) {
		return nil, errorx.New("工作模式设备获取失败", -1)
	}
	for index, cmd := range cmds {
		valInt, _ := strconv.Atoi(cmd.(*go_redis.StringCmd).Val())
		if valInt == workMode {
			arr := strings.Split(keys[index], ":")
			robotIDs = append(robotIDs, arr[len(arr)-1])
		}
	}
	return robotIDs, nil
}

// GetSaleStatusRobotIDs 获取售卖状态下的机器
func (Terminal) GetSaleStatusRobotIDs(saleStatus int) (robotIDs []string, err error) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
	defer cancel()
	rdb := redis.NewDB()
	var scanKeys, keys []string
	var cursor uint64
	for {
		ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
		scanKeys, cursor, err = rdb.Scan(ctx, cursor, "*"+define.RedisRobotRTInfo+"*", 1000).Result()
		cancel()
		keys = append(keys, scanKeys...)
		time.Sleep(time.Millisecond * 50)
		if cursor == 0 {
			break
		}
		if err != nil {
			break
		}
	}
	// 分批获取
	// 防止pipeline过大
	chunks := lo.Chunk(keys, 500)
	for _, keys := range chunks {
		cmds, _ := redis.NewDB().Pipelined(ctx, func(pipe go_redis.Pipeliner) error {
			for _, key := range keys {
				pipe.HGet(ctx, key, "sale_status") // 售卖状态
			}
			return nil
		})
		if len(keys) != len(cmds) {
			return nil, errorx.New("售卖状态设备获取失败", -1)
		}
		for index, cmd := range cmds {
			valInt, _ := strconv.Atoi(cmd.(*go_redis.StringCmd).Val())
			if valInt == saleStatus {
				arr := strings.Split(keys[index], ":")
				if len(arr) == 3 {
					robotIDs = append(robotIDs, arr[len(arr)-1])
				}
			}
		}
	}
	return robotIDs, nil
}

// OnlineStatistics 终端在线数量统计
func (Terminal) OnlineStatistics(
	ctx context.Context,
	query *dal.Query,
	loginUserMerchantID,
	loginUserMerchantPath string,
	merchantPath []string, // 商户id，多个以逗号分隔
	provinceID, cityID, districtID string, //省市区id，多个以逗号分隔
	locationID string, // 位置id，多个以逗号分隔
) (
	totalOnline95, totalOffline95 int64, // 95在线离线统计
	totalOnline97, totalOffline97 int64, // 97在线离线统计
	totalOnline98, totalOffline98 int64, // 98在线离线统计
) {
	t := dal.Terminal
	d := dal.Device
	l := dal.Location
	dx := d.WithContext(ctx)
	lx := l.WithContext(ctx)
	// 获取满足条件的设备id
	{
		// 联合设备表 + 位置表
		dx = dx.LeftJoin(lx, l.ID.EqCol(d.LocationID))
		// group查询条件
		// 省份条件
		areaGroup := l.WithContext(ctx)
		{
			if provinceID != "" {
				areaGroup = areaGroup.Or(l.ProvinceID.In(strings.Split(provinceID, ",")...))
			}
			// 城市条件
			if cityID != "" {
				areaGroup = areaGroup.Or(l.CityID.In(strings.Split(cityID, ",")...))
			}
			// 区县条件
			if districtID != "" {
				areaGroup = areaGroup.Or(l.DistrictID.In(strings.Split(districtID, ",")...))
			}
		}
		// 加上group条件
		dx = dx.Where(areaGroup)
		// 所属位置
		if locationID != "" {
			dx = dx.Where(l.ID.In(strings.Split(locationID, ",")...))
		}
		// 商户过滤
		{
			// 如果不是平台用户，则只能看到自己或下级商户的设备
			if loginUserMerchantID != "1" && loginUserMerchantID != "" {
				dx = dx.Where(d.MerchantPath.Like(loginUserMerchantPath + "%"))
			} else if loginUserMerchantID == "1" {
				dx = dx.Where(d.MerchantPath.Like(">1>%")) // 过滤掉管理员下的设备
			}
			if len(merchantPath) > 0 {
				dx = dx.Where(d.MerchantPath.In(merchantPath...))
			}
		}
		// 过滤掉未启用的设备
		dx = dx.Where(d.LatestActiveTime.Gt(0))
	}
	// 统计各终端类型的在线离线总数
	{
		tx1 := dx.Session(&gorm.Session{}) // newSession
		// 95离线数量
		totalOffline95, _ = tx1.
			Where(d.LatestActiveTime.Lt(time.Now().Unix() - 60)).
			Count()
		// 95在线数量
		totalOnline95, _ = tx1.
			Where(d.LatestActiveTime.Gte(time.Now().Unix() - 60)).
			Count()
		// 97离线数量
		totalOffline97, _ = tx1.
			LeftJoin(t.WithContext(ctx), t.RobotID.EqCol(d.RobotID)).
			Where(t.TerminalType.Eq("97")).
			Where(t.LatestActiveTime.Lt(time.Now().Unix() - 60)).
			Count()
		// 97在线数量
		totalOnline97, _ = tx1.
			LeftJoin(t.WithContext(ctx), t.RobotID.EqCol(d.RobotID)).
			Where(t.TerminalType.Eq("97")).
			Where(t.LatestActiveTime.Gte(time.Now().Unix() - 60)).
			Count()
		// 98离线数量
		totalOffline98, _ = tx1.
			LeftJoin(t.WithContext(ctx), t.RobotID.EqCol(d.RobotID)).
			Where(t.TerminalType.Eq("98")).
			Where(t.LatestActiveTime.Lt(time.Now().Unix() - 60)).
			Count()
		// 98在线数量
		totalOnline98, _ = tx1.
			LeftJoin(t.WithContext(ctx), t.RobotID.EqCol(d.RobotID)).
			Where(t.TerminalType.Eq("98")).
			Where(t.LatestActiveTime.Gte(time.Now().Unix() - 60)).
			Count()
	}
	return
}

// GetCacheStatus 获取缓存的状态
// workMode mode subMode saleStatus
func (Terminal) GetCacheStatus(robotIDs []string) (map[string]map[string]int, error) {
	const statusNum = 4
	// 结果整合
	statusMap := make(map[string]map[string]int)
	// 分批获取
	// 防止pipeline过大
	chunks := lo.Chunk(robotIDs, 100)
	for _, chunkRobotIDs := range chunks {
		// 主模式和子模式
		// 通过redis的pipline批量获取
		ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
		cmds, _ := redis.NewDB().Pipelined(ctx, func(pipe go_redis.Pipeliner) error {
			for _, robotID := range chunkRobotIDs {
				pipe.HGet(ctx, define.RedisRobotRTInfo+robotID, "work_mode")   // 工作模式
				pipe.HGet(ctx, define.RedisRobotRTInfo+robotID, "mode")        // 主模式
				pipe.HGet(ctx, define.RedisRobotRTInfo+robotID, "sub_mode")    // 子模式
				pipe.HGet(ctx, define.RedisRobotRTInfo+robotID, "sale_status") // 售卖状态
			}
			return nil
		})
		cancel()
		if len(chunkRobotIDs) != len(cmds)/statusNum {
			logx.Error(context.Background(), "获取设备状态出现异常")
			return nil, errorx.New("获取设备状态有误", -1)
		}
		for index, cmd := range cmds {
			valInt, _ := strconv.Atoi(cmd.(*go_redis.StringCmd).Val())
			if statusMap[chunkRobotIDs[index/statusNum]] == nil {
				statusMap[chunkRobotIDs[index/statusNum]] = map[string]int{}
			}
			switch index % statusNum {
			case 0:
				statusMap[chunkRobotIDs[index/statusNum]]["work_mode"] = valInt
			case 1:
				statusMap[chunkRobotIDs[index/statusNum]]["mode"] = valInt
			case 2:
				statusMap[chunkRobotIDs[index/statusNum]]["sub_mode"] = valInt
			case 3:
				statusMap[chunkRobotIDs[index/statusNum]]["sale_status"] = valInt
			default:
				logx.Error(context.Background(), "无效的状态")
			}
		}
	}
	return statusMap, nil
}

// GetVolumeSetting 获取音量设置
func (Terminal) GetVolumeSetting(ctx context.Context, query *dal.Query, robotID, terminalType string, volumetype int) (volumePercent int) {
	t := dal.Terminal
	const (
		TerminalTypeDefault = "system98"
		TerminalType98      = "98"
		TerminalType97      = "97"
	)
	var targetTerminalType string
	switch volumetype {
	case 1:
		targetTerminalType = TerminalTypeDefault
	case 2:
		targetTerminalType = TerminalType98
	case 3:
		targetTerminalType = TerminalType97
	default:
		logx.Error(context.Background(), "无效的类型")
		return -1
	}
	res, err := t.WithContext(ctx).
		Where(t.RobotID.Eq(robotID)).
		Where(t.TerminalType.Eq(targetTerminalType)).
		Take()
	if err == nil {
		return res.VolumePercent
	} else {
		return -1
	}
}

// SetVolume 设置音量
func (Terminal) SetVolume(ctx context.Context, query *dal.Query, robotID, terminalType string, volume int, volumetype int) (success bool) {

	const (
		TerminalTypeDefault = "system98"
		TerminalType98      = "98"
		TerminalType97      = "97"
	)
	var targetTerminalType string
	var rowsAffected int64
	switch volumetype {
	case 1:
		targetTerminalType = TerminalTypeDefault
	case 2:
		targetTerminalType = TerminalType98
	case 3:
		targetTerminalType = TerminalType97
	default:
		logx.Error(context.Background(), "无效的类型")
		return false
	}
	// 存在类型就更新，不存在就创建
	db := mysql.NewDB()
	rowsAffected = db.Where(models.Terminal{
		RobotID:      robotID,
		TerminalType: targetTerminalType,
	}).Assign(models.Terminal{
		VolumePercent: volume,
	}).FirstOrCreate(&models.Terminal{}).RowsAffected

	return rowsAffected > 0
}

// Detail 终端详情
func (Terminal) Detail(ctx context.Context, query *dal.Query, robotID string, terminalType string) (*models.Terminal, error) {
	t := dal.Terminal
	return t.WithContext(ctx).
		Where(t.RobotID.Eq(robotID)).
		Where(t.TerminalType.Eq(terminalType)).
		Take()
}

// OnlineStatus 获取终端的在线状态
func (Terminal) OnlineStatus(ctx context.Context, query *dal.Query, robotID string, terminalType string) bool {
	t := dal.Terminal
	count, _ := t.WithContext(ctx).
		Where(t.RobotID.Eq(robotID)).
		Where(t.TerminalType.Eq(terminalType)).
		Where(t.LatestActiveTime.Gt(time.Now().Unix() - 60)).
		Count()
	return count == 1
}

// UpdateArch 更新架构类型
func (Terminal) UpdateArch(ctx context.Context, query *dal.Query, robotID string, terminalType string, arch int) (bool, error) {
	t := dal.Terminal
	res, err := t.WithContext(ctx).
		Where(t.RobotID.Eq(robotID)).
		Where(t.TerminalType.Eq(terminalType)).
		Update(t.Arch, arch)
	if res.RowsAffected == 1 {
		return true, nil
	} else {
		return false, err
	}
}
